package com.neu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neu.base.PageBean;
import com.neu.base.Result;
import com.neu.entity.*;
import com.neu.entity.DTO.InviteProjectUser;
import com.neu.entity.DTO.ProjectDTO;
import com.neu.entity.DTO.RemoveUserProject;
import com.neu.entity.DTO.TaskDTO;
import com.neu.entity.security.LoginUser;
import com.neu.events.UserUpdateEvent;
import com.neu.mapper.ProjectMapper;
import com.neu.mapper.TaskMapper;
import com.neu.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements ProjectService {
    @Autowired
    private ProjectUserRoleService projectUserRoleService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private UserService userService;
    @Autowired
    private TaskUserService taskUserService;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private NoticeService noticeService;
    @Autowired
    private InvitationService invitationService;
    @Autowired
    private TaskMapper taskMapper;
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Autowired
    public void setNoticeService(NoticeService noticeService) {
        this.noticeService = noticeService;
    }

    @Override
    public PageBean<Project> pagelist(Integer pageNum, Integer pageSize) {
        Page<Project> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getDelFlag, "1");// 查询未删除的项目

        //根据当前登录用户的权限查询通知
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();

        if (!permissions.contains("ROLE_super")) {
            queryWrapper.eq(Project::getTenantId, loginUser.getTenantId());
        }

        Page<Project> tenantPage = this.baseMapper.selectPage(page, queryWrapper);
        return new PageBean<>(tenantPage);
    }

    @Override
    public List<Project> findProjectById(List<String> list) {
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Project::getTenantId, list)
                .eq(Project::getDelFlag, "1");// 查询未删除的项目
        return this.list(queryWrapper);
    }

    @Override
    public ProjectDTO findUserByProjectId(String projectId) {
        //先查询项目下的所有角色
        List<ProjectUserRole> projectUserRoles = projectUserRoleService.findByProjectId(projectId);
        Set<Role> roles = roleService.getRoleIdsById(projectUserRoles.stream().map(ProjectUserRole::getRoleId).collect(Collectors.toSet()));
        for (Role role : roles) {
            List<ProjectUserRole> collect = projectUserRoles.stream().
                    filter(projectUserRole -> projectUserRole.getRoleId().equals(role.getRoleId()))
                    .collect(Collectors.toList());//过滤出当前角色下的用户
            if (!collect.isEmpty()) {
                //获取当前角色下的用户
                List<String> userIds = collect.stream().map(ProjectUserRole::getUserId).collect(Collectors.toList());
                role.setUsers(userService.listByIds(userIds));
            }
        }
        Project project = this.getById(projectId);
        ProjectDTO projectDTO = new ProjectDTO();
        BeanUtil.copyProperties(project, projectDTO);
        projectDTO.setRoles(new ArrayList<>(roles));
        return projectDTO;
    }

    @Override
    public ProjectDTO getUsersByType(TaskDTO taskDTO) {
        ProjectDTO projectDTO = findUserByProjectId(taskDTO.getProjectId());
        List<Role> roles = projectDTO.getRoles();
        Role newRole = new Role();
        if (taskDTO.getTaskType().equals("1") || taskDTO.getTaskType().equals("2")) {
            //过滤出评估师
            roles = roles.stream().filter(role -> role.getRoleCode().equals("ROLE_appraiser")).collect(Collectors.toList());
            newRole = roleService.getOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleCode, "ROLE_appraiser"));
        } else if (taskDTO.getTaskType().equals("3")) {
            //过滤出审核员
            roles = roles.stream().filter(role -> role.getRoleCode().equals("ROLE_auditor")).collect(Collectors.toList());
            newRole = roleService.getOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleCode, "ROLE_auditor"));
        }
        if (roles.isEmpty()) {
            newRole.setUsers(null);
            projectDTO.setRoles(Collections.singletonList(newRole));
            return projectDTO;
        }
        List<String> userIds = roles.get(0).getUsers().stream().map(User::getUserId).collect(Collectors.toList());
        LambdaQueryWrapper<TaskUser> taskUserWrapper = new LambdaQueryWrapper();
        taskUserWrapper.in(TaskUser::getTaskId, taskDTO.getTaskId());
        List<TaskUser> taskUsers = taskUserService.list(taskUserWrapper);
        List<String> taskUserIds = taskUsers.stream().map(TaskUser::getUserId).collect(Collectors.toList());
        //在userIds去除taskUserIds
        userIds.removeAll(taskUserIds);
        System.out.println("--------" + userIds);
        if (userIds.isEmpty()) {
            newRole.setUsers(null);
            projectDTO.setRoles(Collections.singletonList(newRole));
            return projectDTO;
        }
        List<User> users = userService.listByIds(userIds);
        newRole.setUsers(users);
        projectDTO.setRoles(Collections.singletonList(newRole));
        return projectDTO;
    }

    @Override
    public ProjectDTO findUserByProjectTask(String projectId, String taskType) {
        ProjectDTO projectDTO = findUserByProjectId(projectId);
        List<Role> roles = projectDTO.getRoles();
        Role newRole = new Role();
        if (taskType.equals("1") || taskType.equals("2")) {
            //过滤出评估师
            roles = roles.stream().filter(role -> role.getRoleCode().equals("ROLE_appraiser")).collect(Collectors.toList());
            newRole = roleService.getOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleCode, "ROLE_appraiser"));
        } else if (taskType.equals("3")) {
            //过滤出审核员
            roles = roles.stream().filter(role -> role.getRoleCode().equals("ROLE_auditor")).collect(Collectors.toList());
            newRole = roleService.getOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleCode, "ROLE_auditor"));
        }
        if (roles.isEmpty()) {
            newRole.setUsers(null);
            projectDTO.setRoles(Collections.singletonList(newRole));
            return projectDTO;
        }
        List<String> userIds = roles.get(0).getUsers().stream().map(User::getUserId).collect(Collectors.toList());
        if (userIds.isEmpty()) {
            newRole.setUsers(null);
            projectDTO.setRoles(Collections.singletonList(newRole));
            return projectDTO;
        }
        List<User> users = userService.listByIds(userIds);
        newRole.setUsers(users);
        projectDTO.setRoles(Collections.singletonList(newRole));
        return projectDTO;
    }

    @Override
    public Project updateState(String projectId, String status) {
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getProjectId, projectId);

        Project project = new Project();
        project.setProjectStatus(status);
        project.setUpdateTime(LocalDateTime.now());

        int rows = this.projectMapper.update(project, queryWrapper);

        if (rows > 0) {
            return this.projectMapper.selectOne(queryWrapper);
        } else {
            throw new RuntimeException("更新失败，可能项目不存在");
        }
    }



    @Override
    public PageBean<Project> search(Map map) {
        Integer pageNum = (Integer) map.get("pageNum");
        Integer pageSize = (Integer) map.get("pageSize");

        // 获取嵌套的 search Map
        Map<String, Object> searchMap = (Map<String, Object>) map.get("search");

        // 从 search Map 中获取值
        String projectname = (String) searchMap.get("projectname");
        String status = (String) searchMap.get("status");
        List<String> createTimeList = (List<String>) searchMap.get("createTimeList");
        List<String> tenantIdList = (List<String>) searchMap.get("tenantIdList");

        //把日期字符串转换为日期对象
        LocalDateTime startTime = null;
        LocalDateTime endTime = null;
        if (createTimeList != null && createTimeList.size() == 2) {
            startTime = OffsetDateTime.parse(createTimeList.get(0), DateTimeFormatter.ISO_OFFSET_DATE_TIME).toLocalDateTime();
            endTime = OffsetDateTime.parse(createTimeList.get(1), DateTimeFormatter.ISO_OFFSET_DATE_TIME).toLocalDateTime();
        }
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        //根据当前登录用户的权限查询
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();
        if (!permissions.contains("ROLE_super")) {
            queryWrapper.eq(Project::getTenantId, loginUser.getTenantId());
        }
        Page<Project> page = new Page<>(pageNum, pageSize);

        queryWrapper.like(StringUtils.hasText(projectname), Project::getProjectName, projectname)
                .eq(StringUtils.hasText(status), Project::getProjectStatus, status)
                .between(createTimeList != null && createTimeList.size() == 2, Project::getStartTime, startTime, endTime)
                .in(!tenantIdList.isEmpty(), Project::getTenantId, tenantIdList);

        Page<Project> userIPage = projectMapper.selectPage(page, queryWrapper);

        return new PageBean<>(userIPage);
    }

    @Override
    public List<User> findUserByTenantIdFilter(Project project) {
        List<User> allUsers = userService.findUserByTenantId(project.getTenantId());
        //不应该过滤出已经在项目中的用户，毕竟一人可以有多个角色
        //我应该做的是邀请用户的时候，判断用户是否是重复邀请
        return allUsers;
    }


    @Override
    @Transactional
    public Result inviteUser(InviteProjectUser inviteProjectUser) throws Exception {
        List<User> userList = inviteProjectUser.getUserList();
        Project project = inviteProjectUser.getProject();
        String roleId = inviteProjectUser.getRoleId();

        if (userList.isEmpty()) {
            return Result.success();
        }

        List<String> userIdsList = userList.stream().map(User::getUserId).collect(Collectors.toList());
        Set<String> userIdRepeatable = new HashSet<>();

        // 获取项目ID，处理新建和已有项目 TODO 原来是这么处理新增和编辑逻辑的
        String projectId = getProjectId(project);

        for (User user : userList) {
            // 检查是否已邀请
            if (isUserAlreadyInvited(projectId, user.getUserId(), roleId)) {
                userIdRepeatable.add(user.getUserId());
            }
        }

        // 发送通知
        String noticeId=sendInviteNotification(userIdsList, userIdRepeatable, project, roleId);
        // 发送邀请链接
        sendInviteLink(userIdsList, userIdRepeatable, project, roleId,noticeId);
        return Result.success(projectId);
    }

    private String getProjectId(Project project) {
        if (StringUtils.hasText(project.getProjectId())) {
            return project.getProjectId();
        } else {
            String newProjectId = UUID.randomUUID().toString().replace("-", "");
            project.setProjectId(newProjectId);
            return newProjectId;
        }
    }

    private boolean isUserAlreadyInvited(String projectId, String userId, String roleId) {
        LambdaQueryWrapper<ProjectUserRole> queryWrapper = new LambdaQueryWrapper<ProjectUserRole>()
                .eq(ProjectUserRole::getProjectId, projectId)
                .eq(ProjectUserRole::getUserId, userId)
                .eq(ProjectUserRole::getRoleId, roleId);
        List<ProjectUserRole> existingRoles = projectUserRoleService.list(queryWrapper);
        return !existingRoles.isEmpty();
    }

    private String sendInviteNotification(List<String> userIdsList, Set<String> userIdRepeatable, Project project, String roleId) {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Role role = roleService.getById(roleId);

        // 过滤掉重复邀请的用户
        List<String> noticeUserIds = userIdsList.stream()
                .filter(userId -> !userIdRepeatable.contains(userId))
                .collect(Collectors.toList());

        String noticeId=noticeService.sendProjectInviteNotice(noticeUserIds, project, role, loginUser);
        return noticeId;
    }

    private void sendInviteLink(List<String> userIdsList, Set<String> userIdRepeatable, Project project, String roleId,String noticeId) throws Exception {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Role role = roleService.getById(roleId);

        // 过滤掉重复邀请的用户
        List<String> noticeUserIds = userIdsList.stream()
                .filter(userId -> !userIdRepeatable.contains(userId))
                .collect(Collectors.toList());

        invitationService.sendProjectInviteLink(noticeUserIds, project, role, loginUser,noticeId);
    }


    @Override
    public Result removeUser(RemoveUserProject removeUserProject) {
        User user = removeUserProject.getUser();
        Project project = removeUserProject.getProject();
        Role role = removeUserProject.getRole();
        //不能移除在该项目下有任务的用户
        List<Task> tasks = taskMapper.selectList(new LambdaQueryWrapper<Task>().eq(Task::getProjectId, project.getProjectId()));
        List<String> taskIds =new ArrayList<>();
        if(!tasks.isEmpty()){
            //说明该项目下有任务
            taskIds = tasks.stream().map(Task::getTaskId).collect(Collectors.toList());
            //查询该用户是否有任务
            List<TaskUser> taskUsers = taskUserService.list(new LambdaQueryWrapper<TaskUser>()
                    .eq(TaskUser::getUserId, user.getUserId())
                    .in(!taskIds.isEmpty(),TaskUser::getTaskId, taskIds)
            );
            if(!taskUsers.isEmpty()){
                return Result.error("用户有任务，不能移除！");
            }
        }

        LambdaQueryWrapper<ProjectUserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProjectUserRole::getProjectId, project.getProjectId())
                .eq(ProjectUserRole::getRoleId, role.getRoleId())
                .eq(ProjectUserRole::getUserId, user.getUserId());

        //更新notice表
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        noticeService.removeProjectInviteNotice(user, project, role, loginUser);
        projectUserRoleService.remove(queryWrapper);
        if (user.getUserId().equals(loginUser.getUserId())) {
            eventPublisher.publishEvent(new UserUpdateEvent(this, user));
        }
        return Result.success();
    }

    @Override
    public List<Project> all() {
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getDelFlag, "1");// 查询未删除的用户

        //根据当前登录用户的权限查询
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();

        if (!permissions.contains("ROLE_super")) {
            queryWrapper.eq(Project::getTenantId, loginUser.getTenantId());
        }
        return this.list(queryWrapper);
    }

    @Override
    public Result removeProject(ProjectDTO projectDTO) {
        String projectId = projectDTO.getProjectId();
        List<ProjectUserRole> projectUserRoles = projectUserRoleService.list(new LambdaQueryWrapper<ProjectUserRole>().eq(ProjectUserRole::getProjectId, projectId));
        if(!projectUserRoles.isEmpty()){
            return Result.error("项目下还有用户参与，不能删除！");
        }

        this.removeById(projectId);
        return Result.success();
    }

    @Override
    public Result removeProjectBatch(List<String> projectIdlist) {
        for (String proId : projectIdlist) {
            List<ProjectUserRole> projectUserRoles = projectUserRoleService.list(new LambdaQueryWrapper<ProjectUserRole>().eq(ProjectUserRole::getProjectId, proId));
            if(!projectUserRoles.isEmpty()){
                Project project = this.getOne(new LambdaQueryWrapper<Project>().eq(Project::getProjectId, proId));
                return Result.error("项目"+project.getProjectName()+"下还有用户参与，不能删除！");
            }

        }

        return Result.success(this.removeByIds(projectIdlist));
    }
}
